package com.zslibrary.Protocol;

import com.zslibrary.Enum.GateStatusDefine;
import com.zslibrary.Enum.PipeResultDefine;
import com.zslibrary.Enum.Protocol;
import com.zslibrary.Enum.StateEventDefine;
import com.zslibrary.Pipe.Pipe;
import com.zslibrary.Structure.GateStruct;
import com.zslibrary.Structure.GeneralRequestStruct;
import com.zslibrary.Structure.MessageStruct;
import com.zslibrary.Structure.ReplyGateStruct;
import com.zslibrary.Tools.FrameBuilder;
import com.zslibrary.Tools.ZSLog;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

public class QueryGateStatus {
    private static Boolean isStatusSuspend=false;
    private static Boolean isStatusDepleted=false;
    private static Boolean isStatusLocked=false;
    private static ReentrantLock globalGateLock=new ReentrantLock(true);
    private static List<GateStruct> componentList=new ArrayList<>();

    public static int queryGateStatus(final Pipe pipe){
        GeneralRequestStruct request=new GeneralRequestStruct();
        List<GateStruct> gateList= Machine.getRequestGateList();
        int gateLen=gateList.size();
        FrameBuilder dataBuilder=new FrameBuilder(gateLen*4+2);
        request.requstId= Protocol.MSG_REQUEST_GATE_STATUS;
        request.dataLength=(short)(gateLen*4+2);
        dataBuilder.append((short)gateLen);
        for(GateStruct gate:gateList){
            dataBuilder.append(gate.componentId);
            dataBuilder.append((short)gate.gateId);
        }
        request.data=dataBuilder.toBytes();
        Pipe.HandleMessageCallback callback=new Pipe.HandleMessageCallback() {
            @Override
            public Boolean handle(MessageStruct[] messages) {
                for(MessageStruct message:messages){
                    switch(message.messageId){
                        case Protocol.MSG_REPLY_GATE_STATUS:{
                            FrameBuilder msgBuilder=new FrameBuilder(message.messageData);
                            int gateLen=(message.messageLength-2)/5;
                            List <ReplyGateStruct> statusList=new ArrayList<>();
                            short[] gates=new short[gateLen];
                            short[] comps=new short[gateLen];
                            for(int i=0;i<gateLen;i++){
                                comps[i]=(short)msgBuilder.popData(2);
                                gates[i]=(short)msgBuilder.popData(2);
                            }
                            int statusLen=msgBuilder.popData(2);
                            for(int i=0;i<gateLen;i++){
                                ReplyGateStruct status=new ReplyGateStruct();
                                status.componentId=comps[i];
                                status.gateId=gates[i];
                                status.status=(byte)msgBuilder.popData(1);
                                statusList.add(status); /*获取到所有状态*/
                            }
                            checkGates(statusList); /*检查缓存状态*/
                            return true;
                        }

                        case Protocol.MSG_SET_COMP_ERR:{
                            CommonMessage.processSetError(message);
                        }break;

                        case Protocol.MSG_CLEAR_COMP_ERR:{
                            CommonMessage.processClrError(message);
                        }break;

                        case Protocol.MSG_BOARD_RESET:{
                            pipe.interruptAsynchonousPipe();    /*可被终止*/
                        }break;

                        default:
                            break;
                    }
                }
                return false;
            }
        };
        int pipeResult=pipe.asynchronousPipe(request,callback,6000);
        if(pipeResult== PipeResultDefine.ASYNC_BUSY)
            return StateEventDefine.EVT_EXECUTE;    /*等待Idle*/
        if(pipeResult==PipeResultDefine.ASYNC_INTERRUPT)
            return StateEventDefine.EVT_RESET;
        if(pipeResult==PipeResultDefine.ASYNC_ERROR)
            return  StateEventDefine.EVT_DISCONNECT;
        return StateEventDefine.EVT_NONE;
    }

    private static void checkGates(List<ReplyGateStruct> statusList){
        try {
            globalGateLock.lock();
            componentList.clear();  //2020_02_13 add:clear
            if (statusList.size() > 0) {
                isStatusSuspend = false;
                isStatusDepleted = false;
                isStatusLocked = false;
            }
            for (ReplyGateStruct status : statusList) {
                if (status.status == GateStatusDefine.GATE_OK)
                    continue;
                if (status.status == GateStatusDefine.GATE_SUSPENDED)
                    isStatusSuspend = true;
                else if (status.status == GateStatusDefine.GATE_LOCKED)
                    isStatusLocked = true;
                else if (status.status == GateStatusDefine.GATE_DEPLETED)
                    isStatusDepleted = true;
                else if (status.status == GateStatusDefine.GATE_ERRORED) {
                    //2020_02_13 modify
                    if(componentList.isEmpty()){
                        GateStruct gate=new GateStruct();
                        gate.componentId=status.componentId;
                        gate.gateId=(byte)status.gateId;
                        componentList.add(gate);
                        ZSLog.d("unvaliable:"+String.valueOf(status.componentId));
                    }else{
                        for(GateStruct g:componentList){
                            if(g.componentId!=status.componentId||g.gateId!=status.gateId){
                                GateStruct gate=new GateStruct();
                                gate.componentId=status.componentId;
                                gate.gateId=(byte)status.gateId;
                                componentList.add(gate);
                                ZSLog.d("unvaliable2:"+String.valueOf(status.componentId));
                            }
                        }
                    }
                }
            }
        }catch(Exception e){
            ZSLog.d(e.toString());
        }finally {
            if(globalGateLock.isHeldByCurrentThread())
                globalGateLock.unlock();
        }
    }

    public static Boolean getGlobalGate(@GateStatusDefine.GateStatusType int gateType){
        try {
            globalGateLock.lock();
            if (gateType == GateStatusDefine.GATE_SUSPENDED) {
                return isStatusSuspend;
            } else if (gateType == GateStatusDefine.GATE_DEPLETED) {
                return isStatusDepleted;
            }
            else if (gateType == GateStatusDefine.GATE_LOCKED) {
                return isStatusLocked;
            }
        }catch (Exception e){
            ZSLog.d(e.toString());
        }finally {
            if(globalGateLock.isHeldByCurrentThread())
                globalGateLock.unlock();
        }
        return false;
    }

    public static List<GateStruct> checkUnusableComponent(){
        return componentList;
    }
}
